/*
 * Copyright (C), 2013-2015, 韩伟
 * FileName: JobExcute.java
 * Author:   yyt
 * Date:     2015年5月12日 上午9:34:54
 * Description: //模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.cango.framework.base.job;

import com.alibaba.fastjson.JSONObject;
import com.cango.framework.base.opt.DictUtils;
import com.cango.framework.base.util.Container;
import com.cango.mail.controller.MailController;
import com.cango.qutz.web.entity.ScheduleExecution;
import com.cango.qutz.web.entity.ScheduleJob;
import com.cango.qutz.web.entity.ScheduleParam;
import com.cango.qutz.web.job.IScheduleService;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.SimpleMailMessage;

import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 〈一句话功能简述〉<br>
 * 定时任务的执行方法
 *
 * @author yyt
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class JobExecute implements Serializable {

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = -5142683130617745820L;
    /**
     * log
     */
    private final Log logger = LogFactory.getLog(JobExecute.class);


    IScheduleService scheduleService;

    /**
     * 功能描述: <br>
     * 具体的执行方法
     *
     * @param job 任务信息
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public void execute(ScheduleJob job) {

        Date beginDate = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = format.format(beginDate);
        String executeResult = "1";
        String executeType = StringUtils.isEmpty(job.getExecuteType())?"1":job.getExecuteType();
        String remark = "";
        String paraStr = "";
        Object result = null;
        ScheduleJob executeJob  = null;
        try {

            scheduleService = (IScheduleService) Container.getBean("scheduleService");
            logger.debug("============ execute " + nowTime + " ============");

            //查询参数：无参数传入null，有参数的一律使用Map<String,Object>
            List<ScheduleParam> paramList = scheduleService.queryParamsBySchedule(job.getScheduleId());
            executeJob = scheduleService.getScheduleInfoBySid(job.getScheduleId());

            Map<String, Object> param = new HashMap<String, Object>();
            if (null != paramList && !paramList.isEmpty()) {
                for (ScheduleParam p : paramList) {
                    param.put(p.getParamName(), p.getParamSet());
                }
            }
            Gson gson = new Gson();
            paraStr = gson.toJson(param);

            //调用方法
            RestTemplate template = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            //headers.setContentType(MediaType.TEXT_HTML);
            String encParaStr  = "";



            MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<String, String>();
            paramMap.add("method",executeJob.getMethodName());
            try {
                JsonObject json = new JsonObject();
                json.addProperty("authCode",executeJob.getAuthCode());
                json.addProperty("data",paraStr);
                paramMap.add("params",EnUtil.encrypt(json.toString(),executeJob.getPrivateKey()));
            }catch (Exception e){
                logger.error("加密请求参数错误",e);
                throw  new RuntimeException("加密请求参数错误");
            }

            HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<MultiValueMap<String, String>>(paramMap, headers);

            ResponseEntity<String> responseEntity = template.exchange(executeJob.getUrl(), HttpMethod.POST, httpEntity, String.class);
           // JsonObject json = new JsonObject();
            JsonObject json  = gson.fromJson(responseEntity.getBody(),JsonObject.class);
            if(!"0000".equals(json.get("code").getAsString())){
                executeResult = "2";
                remark = json.toString();
                throw new Exception(json.toString());
            }else{
                executeResult = "1";
            }
            remark  = json.toString();
        } catch (Exception e) {
            logger.error("执行任务"+job.getJobFactName()+"发生错误：" + e);
            StringWriter sw = new StringWriter();
            if("".equals(remark)) {
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                executeResult = "2";
                remark = sw.toString();
            }
            //执行发生错误，异步发送邮件个邮件接收人
            SimpleMailMessage msg = new SimpleMailMessage();

            String mailto = executeJob.getMailTo();
            if (!StringUtils.isEmpty(mailto)) {
                ExecutorService s = Executors.newCachedThreadPool();
                JobMailAdder ja = new JobMailAdder();
                ja.setExecuteJob(executeJob);
                ja.setJobId(job.getJobId());
                ja.setParaStr(paraStr);
                ja.setRemark(remark);
                s.execute(ja);
            }
        }finally {
            Date endDate = new Date();
            ScheduleExecution execution = new ScheduleExecution();
            execution.setScheduleId(executeJob.getScheduleId());
            execution.setExecuteTime(beginDate);
            execution.setExecuteEndTime(endDate);
            execution.setParamDetail(paraStr);
            execution.setExecuteType(executeType);
            execution.setExecuteResult(executeResult);
            execution.setRemark(remark);
            execution.setExecuteLength((int) (endDate.getTime() - beginDate.getTime()) / 1000);
            //无论是否执行成功，插入执行记录
            scheduleService.insertExecution(execution);
        }
    }

    class JobMailAdder implements Runnable{
        private ScheduleJob executeJob;
        private String jobId;
        private String remark;
        private String paraStr;

        public ScheduleJob getExecuteJob() {
            return executeJob;
        }

        public void setExecuteJob(ScheduleJob executeJob) {
            this.executeJob = executeJob;
        }

        public String getJobId() {
            return jobId;
        }

        public void setJobId(String jobId) {
            this.jobId = jobId;
        }

        public String getRemark() {
            return remark;
        }

        public void setRemark(String remark) {
            this.remark = remark;
        }

        public String getParaStr() {
            return paraStr;
        }

        public void setParaStr(String paraStr) {
            this.paraStr = paraStr;
        }

        @Override
        public void run() {
            RestTemplate restTemplate = new RestTemplate();
            DictUtils dictUtils = (DictUtils) Container.getBean("dictUtils");

            JSONObject jsonObject = new JSONObject();

            //jsonObject.put("clientCode","dsp");
            JSONObject mailJson = new JSONObject();
            mailJson.put("authCode",dictUtils.getDictEntity(900040002).getDictName());
            mailJson.put("templateCode","job_error");
            mailJson.put("to",getExecuteJob().getMailTo());
            JSONObject spJson = new JSONObject();
            spJson.put("jobId", getJobId());
            spJson.put("scheduleId", getExecuteJob().getScheduleId());
            spJson.put("jobGroup", getExecuteJob().getJobGroup());
            spJson.put("jobName", getExecuteJob().getJobName());
            spJson.put("methodName", getExecuteJob().getMethodName());
            spJson.put("clientCode", getExecuteJob().getClientCode());
            spJson.put("remark", getExecuteJob().getRemark());
            spJson.put("param", paraStr);
            Date beginDate = new Date();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String nowTime = format.format(beginDate);
            spJson.put("executeTime", nowTime);
            if(null != remark && remark.length()>500){
                setRemark(getRemark().substring(0,499));
            }
            spJson.put("error", getRemark().replaceAll("\t", "        "));
            mailJson.put("sp",spJson);

            mailJson.put("cp",spJson);
            jsonObject.put("data",mailJson);
            try {
                String s= MailController.encrypt(jsonObject.toJSONString(),dictUtils.getDictEntity(900040001).getDictName());

                HttpHeaders headers = new HttpHeaders();
                MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
                params.add("params",s);
                params.add("clientCode","dsp");

                HttpEntity entity = new HttpEntity(params, headers);
                ResponseEntity<String> responseEntity = restTemplate.exchange(dictUtils.getDictEntity(900030003).getDictName(),HttpMethod.POST,entity,String.class);
                //System.out.println(responseEntity.getBody());
                logger.info(responseEntity.getBody());
            } catch (Exception e) {
                logger.error("job加密发送邮件内容",e);
            }
        }
    }
}
